import uvm_pkg::*;
`include "uvm_macros.svh"

class mpi_driver extends uvm_driver #(mpi_xaction);
	`uvm_component_utils(mpi_driver);
	
	virtual mpi_interface vif;
	
	`ifdef FCOV_ON
		mpi_fcov fcov;
	`endif
	
	extern function new(string name, uvm_component parent);
	extern virtual function void build_phase(uvm_phase phase);
	extern virtual task run_phase(uvm_phase phase);//xky_temp
	extern virtual task reset();
	extern virtual task send_stimulus_data();
	extern virtual task mpi_write(input mpi_xaction tr);
	extern virtual task mpi_read(ref mpi_xaction tr);
	extern virtual task drv_random();
	
endclass: mpi_driver

function mpi_driver::new(string name, uvm_component parent);
	super.new(name,parent);
	
	`ifdef FCOV_ON
		this.fcov = mpi_fcov::type_id::create("fcov",this);
	`endif
endfunction: new

function void mpi_driver::build_phase(uvm_phase phase);
	super.build_phase(phase);
	if(!uvm_config_db#(virtual mpi_interface)::get(this,"","vif",this.vif))begin
		`uvm_error(get_type_name(), "build_phase(): Virtual interface in mpi_driver is not configured");
	end
endfunction: build_phase

task mpi_driver::run_phase(uvm_phase phase);
	super.run_phase(phase);

	`uvm_info(get_type_name(),"run_phase(): mpi_driver run_phase is running", UVM_LOW);
	this.reset();
	this.send_stimulus_data();

endtask: run_phase

task mpi_driver::send_stimulus_data();
	mpi_xaction drv_tr;

	@(posedge vif.rst_n);
	while(1) begin
		if(seq_item_port.has_do_available())begin
			seq_item_port.get_next_item(req);
			if(!$cast(drv_tr,req))begin
				`uvm_fatal(get_type_name(),"send_stimulus_data(): req is not a mpi_xactions type or its extension");

			`uvm_info(get_type_name(),"send_stimulus_data(): Get the input transaction", UVM_LOW);

			drv_tr.randomize();
			case(drv_tr.op_type)
			endcase
			end
		end
	end
endtask: send_stimulus_data

